namespace ASPNET.StarterKit.IssueTracker.BusinessLogicLayer
{
    using System;
    using System.Collections;
    using System.Reflection;

    public class IssueCollection : CollectionBase
    {
        public int Add(Issue value)
        {
            return this.List.Add(value);
        }

        public bool Contains(Issue value)
        {
            return this.List.Contains(value);
        }

        public int IndexOf(Issue value)
        {
            return this.List.IndexOf(value);
        }

        public void Insert(int index, Issue value)
        {
            this.List.Insert(index, value);
        }

        protected override void OnInsert(int index, object value)
        {
            if (value.GetType() != Type.GetType("ASPNET.StarterKit.IssueTracker.BusinessLogicLayer.Issue"))
            {
                throw new ArgumentException("value must be of type Issue.", "value");
            }
        }

        protected override void OnRemove(int index, object value)
        {
            if (value.GetType() != Type.GetType("ASPNET.StarterKit.IssueTracker.BusinessLogicLayer.Issue"))
            {
                throw new ArgumentException("value must be of type Issue.", "value");
            }
        }

        protected override void OnSet(int index, object oldValue, object newValue)
        {
            if (newValue.GetType() != Type.GetType("ASPNET.StarterKit.IssueTracker.BusinessLogicLayer.Issue"))
            {
                throw new ArgumentException("newValue must be of type Issue.", "newValue");
            }
        }

        protected override void OnValidate(object value)
        {
            if (value.GetType() != Type.GetType("ASPNET.StarterKit.IssueTracker.BusinessLogicLayer.Issue"))
            {
                throw new ArgumentException("value must be of type Issue.");
            }
        }

        public void Remove(Issue value)
        {
            this.List.Remove(value);
        }

        public void Sort(IssueFields sortField, bool isAscending)
        {
            switch (sortField)
            {
                case IssueFields.Id:
                    this.InnerList.Sort(new IdComparer());
                    break;

                case IssueFields.Category:
                    this.InnerList.Sort(new CategoryComparer());
                    break;

                case IssueFields.Title:
                    this.InnerList.Sort(new TitleComparer());
                    break;

                case IssueFields.Assigned:
                    this.InnerList.Sort(new AssignedComparer());
                    break;

                case IssueFields.Owner:
                    this.InnerList.Sort(new OwnerComparer());
                    break;

                case IssueFields.Creator:
                    this.InnerList.Sort(new CreatorComparer());
                    break;

                case IssueFields.Priority:
                    this.InnerList.Sort(new PriorityComparer());
                    break;

                case IssueFields.Status:
                    this.InnerList.Sort(new StatusComparer());
                    break;

                case IssueFields.Milestone:
                    this.InnerList.Sort(new MilestoneComparer());
                    break;

                case IssueFields.Created:
                    this.InnerList.Sort(new CreatedComparer());
                    break;
            }
            if (!isAscending)
            {
                this.InnerList.Reverse();
            }
        }

        public Issue this[int index]
        {
            get
            {
                return (Issue) this.List[index];
            }
            set
            {
                this.List[index] = value;
            }
        }

        private sealed class AssignedComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return first.AssignedDisplayName.CompareTo(second.AssignedDisplayName);
            }
        }

        private sealed class CategoryComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return first.CategoryName.CompareTo(second.CategoryName);
            }
        }

        private sealed class CreatedComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return first.DateCreated.CompareTo(second.DateCreated);
            }
        }

        private sealed class CreatorComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return first.CreatorDisplayName.CompareTo(second.CreatorDisplayName);
            }
        }

        private sealed class IdComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return (first.Id - second.Id);
            }
        }

        public enum IssueFields
        {
            InitValue,
            Id,
            Category,
            Title,
            Assigned,
            Owner,
            Creator,
            Priority,
            Status,
            Milestone,
            Created
        }

        private sealed class MilestoneComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return first.MilestoneName.CompareTo(second.MilestoneName);
            }
        }

        private sealed class OwnerComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return first.OwnerDisplayName.CompareTo(second.OwnerDisplayName);
            }
        }

        private sealed class PriorityComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return first.PriorityName.CompareTo(second.PriorityName);
            }
        }

        private sealed class StatusComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return first.StatusName.CompareTo(second.StatusName);
            }
        }

        private sealed class TitleComparer : IComparer
        {
            public int Compare(object x, object y)
            {
                Issue first = (Issue) x;
                Issue second = (Issue) y;
                return first.Title.CompareTo(second.Title);
            }
        }
    }
}

